package com.songhuan.web.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.songhuan.web.dto.*;
import com.songhuan.web.dto.query.*;
import com.songhuan.web.entity.*;
import com.songhuan.web.mapper.*;
import com.songhuan.web.service.*;
import com.songhuan.web.tools.dto.*;
import com.songhuan.web.tools.Extension;
import com.songhuan.web.tools.exception.CustomException;
import com.songhuan.web.dto.AppUserDto;
import com.songhuan.web.dto.OrganizationDto;
import com.songhuan.web.dto.ReCheckDto;
import com.songhuan.web.dto.query.ReCheckPagedInput;
import com.songhuan.web.entity.AppUser;
import com.songhuan.web.entity.Enums;
import com.songhuan.web.entity.Organization;
import com.songhuan.web.entity.ReCheck;
import com.songhuan.web.mapper.AppUserMapper;
import com.songhuan.web.mapper.OrganizationMapper;
import com.songhuan.web.mapper.ReCheckMapper;
import com.songhuan.web.service.ReCheckService;
import com.songhuan.web.tools.dto.PagedResult;
import org.apache.commons.beanutils.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.util.List;

import lombok.SneakyThrows;
import com.songhuan.web.tools.*;

/**
 * 补卡记录功能实现类
 */
@Service
public class ReCheckServiceImpl extends ServiceImpl<ReCheckMapper, ReCheck> implements ReCheckService {

    /**
     * 操作数据库AppUser表mapper对象
     */
    @Autowired
    private AppUserMapper _AppUserMapper;
    /**
     * 操作数据库的ReCheck表mapper对象
     */
    @Autowired
    private ReCheckMapper _ReCheckMpper;


    @Autowired
    private OrganizationMapper _OrganizationMapper;


    /**
     * 补卡记录分页查询
     */
    @SneakyThrows
    @Override
    public PagedResult<ReCheckDto> List(ReCheckPagedInput input) {


        //声明一个支持补卡记录查询的(拉姆达)表达式
        LambdaQueryWrapper<ReCheck> queryWrapper = Wrappers.<ReCheck>lambdaQuery()
                .eq(input.getId() != null && input.getId() != 0, ReCheck::getId, input.getId())
                .eq(input.getCreatorId() != null, ReCheck::getCreatorId, input.getCreatorId());
        //如果前端搜索传入查询条件则拼接查询条件
        if (input.getBeginTimeRange() != null && input.getBeginTimeRange().stream().count() > 1) {
            queryWrapper = queryWrapper.lt(ReCheck::getBeginTime, input.getBeginTimeRange().get(1));
            queryWrapper = queryWrapper.gt(ReCheck::getBeginTime, input.getBeginTimeRange().get(0));
        }
        if (input.getOrganizationId() != null) {
            queryWrapper = queryWrapper.eq(ReCheck::getOrganizationId, input.getOrganizationId());
        }
        if (input.getUserId() != null) {
            queryWrapper = queryWrapper.eq(ReCheck::getUserId, input.getUserId());
        }

        if (Extension.isNotNullOrEmpty(input.getReason())) {
            queryWrapper = queryWrapper.eq(ReCheck::getReason, input.getReason());
        }

        if (Extension.isNotNullOrEmpty(input.getReply())) {
            queryWrapper = queryWrapper.eq(ReCheck::getReply, input.getReply());
        }
        if (input.getAuditUserId() != null) {
            queryWrapper = queryWrapper.eq(ReCheck::getAuditUserId, input.getAuditUserId());
        }
        if (input.getAuditStatus() != null) {
            queryWrapper = queryWrapper.eq(ReCheck::getAuditStatus, input.getAuditStatus());
        }
        if (input.getEndTimeRange() != null && input.getEndTimeRange().stream().count() > 1) {
            queryWrapper = queryWrapper.lt(ReCheck::getEndTime, input.getEndTimeRange().get(1));
            queryWrapper = queryWrapper.gt(ReCheck::getEndTime, input.getEndTimeRange().get(0));
        }

        //按创建时间从大到小排序 最新的显示在最前面
        queryWrapper = queryWrapper.orderByDesc(ReCheck::getCreationTime);
        //构建一个分页查询的model
        Page<ReCheck> page = new Page<>(input.getPage(), input.getLimit());


        //从数据库进行分页查询获取补卡记录数据
        IPage<ReCheck> pageRecords = _ReCheckMpper.selectPage(page, queryWrapper);

        //获取所有满足条件的数据行数
        Long totalCount = _ReCheckMpper.selectCount(queryWrapper);

        //把ReCheck实体转换成ReCheck传输模型
        List<ReCheckDto> items = Extension.copyBeanList(pageRecords.getRecords(), ReCheckDto.class);
        for (ReCheckDto item : items) {

            //查询出关联的创建用户信息
            AppUserDto CreatorAppUserDTO = new AppUserDto();
            AppUser CreatorAppUserEntity = _AppUserMapper.selectOne(Wrappers.<AppUser>lambdaQuery().eq(AppUser::getId, item.getCreatorId()));
            if (CreatorAppUserEntity != null) {
                BeanUtils.copyProperties(CreatorAppUserDTO, CreatorAppUserEntity);
                item.setCreatorAppUserDto(CreatorAppUserDTO);
            }


            //查询出关联的Organization表信息
            OrganizationDto OrganizationDTO = new OrganizationDto();
            Organization OrganizationEntity = _OrganizationMapper.selectOne(Wrappers.<Organization>lambdaQuery().eq(Organization::getId, item.getOrganizationId()));
            if (OrganizationEntity != null) {
                BeanUtils.copyProperties(OrganizationDTO, OrganizationEntity);
                item.setOrganizationDto(OrganizationDTO);
            }


            //查询出关联的AppUser表信息
            AppUserDto UserDTO = new AppUserDto();
            AppUser UserEntity = _AppUserMapper.selectOne(Wrappers.<AppUser>lambdaQuery().eq(AppUser::getId, item.getUserId()));
            if (UserEntity != null) {
                BeanUtils.copyProperties(UserDTO, UserEntity);
                item.setUserDto(UserDTO);
            }


            //查询出关联的AppUser表信息
            AppUserDto AuditUserDTO = new AppUserDto();
            AppUser AuditUserEntity = _AppUserMapper.selectOne(Wrappers.<AppUser>lambdaQuery().eq(AppUser::getId, item.getAuditUserId()));
            if (AuditUserEntity != null) {
                BeanUtils.copyProperties(AuditUserDTO, AuditUserEntity);
                item.setAuditUserDto(AuditUserDTO);
            }

        }

        //返回一个分页结构给前端
        return PagedResult.GetInstance(items, totalCount);

    }

    /**
     * 单个补卡记录查询
     */
    @SneakyThrows
    @Override
    public ReCheckDto Get(ReCheckPagedInput input) {
        if (input.getId() == null) {
            return new ReCheckDto();
        }
        PagedResult<ReCheckDto> pagedResult = List(input);
        return pagedResult.getTotalCount() > 0 ? pagedResult.getItems().stream().findFirst().get() : new ReCheckDto();
    }

    /**
     * 补卡记录创建或者修改
     */
    @SneakyThrows
    @Override
    public ReCheckDto CreateOrEdit(ReCheckDto input) {

        //声明一个补卡记录实体
        ReCheck ReCheck = new ReCheck();

        //把前端传入的input参数拷贝到补卡记录实体
        BeanUtils.copyProperties(ReCheck, input);

        //调用数据库的增加或者修改方法
        saveOrUpdate(ReCheck);

        //定义一个返回给前端的补卡记录传输模型
        ReCheckDto ReCheckDto = new ReCheckDto();

        //同理把操作的补卡记录实体拷贝给补卡记录传输模型
        BeanUtils.copyProperties(ReCheckDto, ReCheck);

        //把传输模型返回给前端
        return ReCheckDto;
    }

    /**
     * 补卡申请
     */
    @SneakyThrows
    @Override
    public void Apply(ReCheckDto input) {



        LocalDate localDate = input.getBeginTime().toLocalDate();

        if(!input.getSelectDate().equals(localDate)){
            throw new CustomException("选择的日期和申请的日期不一致");
        }
        //如果开始时间大于结束时间或者等于
        if (input.getBeginTime().isAfter(input.getEndTime()) || input.getBeginTime().isEqual(input.getEndTime())) {
            throw new CustomException("开始时间不能大于结束时间");
        }

        //查询没有审核的补卡记录 申请的日期
        List<ReCheck> reChecks = _ReCheckMpper.selectList(Wrappers.<ReCheck>lambdaQuery().eq(ReCheck::getUserId, input.getUserId()).eq(ReCheck::getAuditStatus, Enums.AuditStatus.待审核.index()));
        //是否存在这个记录的申请
        if (reChecks.stream().anyMatch(x -> x.getBeginTime().toLocalDate().equals(localDate))) {
            throw new CustomException("已经存在申请记录");
        }

        input.setAuditStatus(Enums.AuditStatus.待审核.index());

        //声明一个补卡记录实体
        ReCheck ReCheck = new ReCheck();

        //把前端传入的input参数拷贝到补卡记录实体
        BeanUtils.copyProperties(ReCheck, input);

        //调用数据库的增加或者修改方法
        saveOrUpdate(ReCheck);


    }

    /**
     * 补卡审核通过
     */
    @SneakyThrows
    @Override
    public void ApplySuccess(ReCheckDto input) {

        input.setAuditStatus(Enums.AuditStatus.审核通过.index());
        input.setReply("审核通过");
        //声明一个补卡记录实体
        ReCheck ReCheck = new ReCheck();

        //把前端传入的input参数拷贝到补卡记录实体
        BeanUtils.copyProperties(ReCheck, input);

        //调用数据库的增加或者修改方法
        saveOrUpdate(ReCheck);

    }


}
